package com.nbcio.iot.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.lang.tree.Tree;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.nbcio.common.core.constant.UserConstants;
import com.nbcio.common.core.exception.ServiceException;
import com.nbcio.common.core.utils.MapstructUtils;
import com.nbcio.common.core.utils.StringUtils;
import com.nbcio.common.core.utils.TreeBuildUtils;
import com.nbcio.iot.domain.bo.IotProductCategoryBo;
import com.nbcio.iot.domain.entity.IotProductCategory;
import com.nbcio.iot.domain.vo.IotProductCategoryVo;
import com.nbcio.iot.mapper.IotProductCategoryMapper;
import com.nbcio.iot.service.IIotProductCategoryService;
import com.nbcio.iot.service.IIotProductService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * 物联网产品分类服务实现
 */
@Service
@RequiredArgsConstructor
public class IotProductCategoryServiceImpl implements IIotProductCategoryService {

    private final IotProductCategoryMapper baseMapper;
    private final IIotProductService productService;

    @Override
    public List<IotProductCategoryVo> selectCategoryList(IotProductCategoryBo bo) {
        LambdaQueryWrapper<IotProductCategory> lqw = buildQueryWrapper(bo);
        // 直接使用 selectList 然后转换
        List<IotProductCategory> list = baseMapper.selectList(lqw);
        List<IotProductCategoryVo> voList = MapstructUtils.convert(list, IotProductCategoryVo.class);
        
        // 统计每个分类下的产品数量
        for (IotProductCategoryVo category : voList) {
            long productCount = productService.countByCategoryId(category.getCategoryId());
            category.setProductCount((int) productCount);
        }
        return voList;
    }

    @Override
    public List<Tree<Long>> selectCategoryTreeList(IotProductCategoryBo bo) {
        // 只查询正常状态分类
        bo.setStatus(UserConstants.NORMAL);
        List<IotProductCategoryVo> list = selectCategoryList(bo);
        return buildCategoryTreeSelect(list);
    }

    @Override
    public List<Tree<Long>> buildCategoryTreeSelect(List<IotProductCategoryVo> categories) {
        if (CollUtil.isEmpty(categories)) {
            return CollUtil.newArrayList();
        }
        return TreeBuildUtils.build(categories, (category, tree) ->
            tree.setId(category.getCategoryId())
                .setParentId(category.getParentId())
                .setName(category.getCategoryName())
                .setWeight(category.getOrderNum()));
    }

    @Override
    public IotProductCategoryVo selectCategoryById(Long categoryId) {
        IotProductCategory category = baseMapper.selectById(categoryId);
        if (ObjectUtil.isNull(category)) {
            throw new ServiceException("产品分类不存在");
        }
        IotProductCategoryVo vo = MapstructUtils.convert(category, IotProductCategoryVo.class);
        
        // 设置父分类名称
        if (vo.getParentId() != null && vo.getParentId() != 0) {
            IotProductCategory parent = baseMapper.selectById(vo.getParentId());
            if (ObjectUtil.isNotNull(parent)) {
                vo.setParentName(parent.getCategoryName());
            }
        }
        
        return vo;
    }

    @Override
    public boolean hasChildByCategoryId(Long categoryId) {
        LambdaQueryWrapper<IotProductCategory> lqw = Wrappers.lambdaQuery();
        lqw.eq(IotProductCategory::getParentId, categoryId);
        return baseMapper.selectCount(lqw) > 0;
    }

    @Override
    public boolean checkCategoryNameUnique(IotProductCategoryBo bo) {
        LambdaQueryWrapper<IotProductCategory> lqw = Wrappers.lambdaQuery();
        lqw.eq(IotProductCategory::getCategoryName, bo.getCategoryName())
            .eq(IotProductCategory::getParentId, bo.getParentId())
            .ne(ObjectUtil.isNotNull(bo.getCategoryId()), IotProductCategory::getCategoryId, bo.getCategoryId());
        return baseMapper.selectCount(lqw) == 0;
    }

    @Override
    public boolean checkCategoryCodeUnique(IotProductCategoryBo bo) {
        LambdaQueryWrapper<IotProductCategory> lqw = Wrappers.lambdaQuery();
        lqw.eq(IotProductCategory::getCategoryCode, bo.getCategoryCode())
            .ne(ObjectUtil.isNotNull(bo.getCategoryId()), IotProductCategory::getCategoryId, bo.getCategoryId());
        return baseMapper.selectCount(lqw) == 0;
    }

    @Override
    public Boolean insertCategory(IotProductCategoryBo bo) {
        IotProductCategory category = MapstructUtils.convert(bo, IotProductCategory.class);
        validEntityBeforeSave(bo);
        boolean flag = baseMapper.insert(category) > 0;
        if (flag) {
            // 更新祖级列表
            updateCategoryAncestors(category);
        }
        return flag;
    }

    @Override
    public Boolean updateCategory(IotProductCategoryBo bo) {
        IotProductCategory category = MapstructUtils.convert(bo, IotProductCategory.class);
        validEntityBeforeSave(bo);
        IotProductCategory oldCategory = baseMapper.selectById(category.getCategoryId());
        boolean flag = baseMapper.updateById(category) > 0;
        if (flag) {
            // 更新祖级列表
            updateCategoryAncestors(category);
            // 如果父分类发生变化，更新子分类的祖级列表
            if (!ObjectUtil.equals(oldCategory.getParentId(), category.getParentId())) {
                updateChildrenCategoryAncestors(category);
            }
        }
        return flag;
    }

    @Override
    public Boolean deleteCategoryByIds(List<Long> categoryIds) {
        for (Long categoryId : categoryIds) {
            validEntityBeforeDelete(categoryId);
        }
        return baseMapper.deleteBatchIds(categoryIds) > 0;
    }

    /**
     * 构建查询条件
     */
    private LambdaQueryWrapper<IotProductCategory> buildQueryWrapper(IotProductCategoryBo bo) {
        LambdaQueryWrapper<IotProductCategory> lqw = Wrappers.lambdaQuery();
        lqw.like(StringUtils.isNotBlank(bo.getCategoryName()), IotProductCategory::getCategoryName, bo.getCategoryName())
            .eq(StringUtils.isNotBlank(bo.getCategoryCode()), IotProductCategory::getCategoryCode, bo.getCategoryCode())
            .eq(ObjectUtil.isNotNull(bo.getParentId()), IotProductCategory::getParentId, bo.getParentId())
            .eq(StringUtils.isNotBlank(bo.getStatus()), IotProductCategory::getStatus, bo.getStatus())
            .orderByAsc(IotProductCategory::getParentId, IotProductCategory::getOrderNum, IotProductCategory::getCategoryId);
        return lqw;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(IotProductCategoryBo bo) {
        // 校验分类名称唯一性
        if (!checkCategoryNameUnique(bo)) {
            throw new ServiceException("新增产品分类'" + bo.getCategoryName() + "'失败，分类名称已存在");
        }
        // 校验分类编码唯一性
        if (!checkCategoryCodeUnique(bo)) {
            throw new ServiceException("新增产品分类'" + bo.getCategoryName() + "'失败，分类编码已存在");
        }
    }

    /**
     * 删除前的数据校验
     */
    private void validEntityBeforeDelete(Long categoryId) {
        // 检查是否存在子分类
        if (hasChildByCategoryId(categoryId)) {
            throw new ServiceException("存在子分类，不允许删除");
        }
        // 检查是否存在产品
        if (productService.countByCategoryId(categoryId) > 0) {
            throw new ServiceException("分类下存在产品，不允许删除");
        }
    }

    /**
     * 更新分类的祖级列表
     */
    private void updateCategoryAncestors(IotProductCategory category) {
        IotProductCategory parent = baseMapper.selectById(category.getParentId());
        if (ObjectUtil.isNotNull(parent)) {
            String ancestors = parent.getAncestors() + "," + parent.getCategoryId();
            category.setAncestors(ancestors);
            baseMapper.updateById(category);
        }
    }

    /**
     * 更新子分类的祖级列表
     */
    private void updateChildrenCategoryAncestors(IotProductCategory category) {
        List<IotProductCategory> children = baseMapper.selectList(
            Wrappers.lambdaQuery(IotProductCategory.class)
                .like(IotProductCategory::getAncestors, category.getCategoryId())
        );
        for (IotProductCategory child : children) {
            String ancestors = category.getAncestors() + "," + category.getCategoryId();
            child.setAncestors(ancestors);
            baseMapper.updateById(child);
        }
    }
} 